package com.pubinfo.passbook.data.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.mashape.unirest.http.Unirest;
import com.mashape.unirest.http.exceptions.UnirestException;
import com.mashape.unirest.request.GetRequest;
import com.pubinfo.passbook.common.entity.TFileInfo;
import com.pubinfo.passbook.common.entity.TPassbook;
import com.pubinfo.passbook.common.mapper.TFileInfoMapper;
import com.pubinfo.passbook.common.mapper.TSourcePassbookMapper;
import com.pubinfo.passbook.common.mapper.TSubsidiaryPrivateKeyMapper;
import com.pubinfo.passbook.common.model.bo.SubsidiaryInfo;
import com.pubinfo.passbook.common.model.vo.base.JsonResult;
import com.pubinfo.passbook.common.service.master.TPassbookService;
import com.pubinfo.passbook.common.service.request.financial.RequestFinancialServer;
import com.pubinfo.passbook.data.service.DownLoadPDFService;
import com.pubinfo.passbook.data.service.TFileInfoService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.entity.ContentType;
import org.apache.pdfbox.io.MemoryUsageSetting;
import org.apache.pdfbox.multipdf.PDFMergerUtility;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;

import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static java.util.regex.Pattern.compile;

@Service
@Slf4j
public class DownLoadPdfServiceImpl implements DownLoadPDFService {

    @Value("${file.uploadFolder}")
    private String filePath;
    @Autowired
    TFileInfoService tFileInfoService;
    @Autowired
    TSourcePassbookMapper tSourcePassbookMapper;
    @Autowired
    TFileInfoMapper tFileInfoMapper;
    @Autowired
    private TSubsidiaryPrivateKeyMapper keyMapper;
    @Autowired
    RequestFinancialServer financialServer;
    @Autowired
    TPassbookService tPassbookService;

    @Override
    public void downLoadPDFByEInvoiceId(String eInvoiceId) {
        TPassbook passbook = tSourcePassbookMapper.selectByEInvoiceId(eInvoiceId);
        downLoad(passbook);
    }

    @Override
    public void downLoadPDFByPassbook(List<TPassbook> passbookList) {
        //过滤没有下载的票据
        List<TPassbook> destList = new ArrayList<TPassbook>(passbookList);

        destList.removeIf(t -> (t.getIsDownload()));
        if (CollectionUtils.isEmpty(destList)) {
            return;
        }
        destList.stream().forEach(t -> {
            downLoad(t);
        });
    }

    @Override
    public void downLoadPDF() {
        List<TPassbook> passbookList = tSourcePassbookMapper.selectNotDownload();

        //先修复一遍数据
        List<TPassbook> newPassbook = new ArrayList<>();
        if (!org.springframework.util.CollectionUtils.isEmpty(passbookList)) {
            Map<String, List<TPassbook>> nsrsbhMap = passbookList.stream().collect(Collectors.groupingBy(TPassbook::getNsrsbh));
            for (Map.Entry<String, List<TPassbook>> entry : nsrsbhMap.entrySet()) {
                String nsrsbh = entry.getKey();
                List<TPassbook> passbooks = entry.getValue();
                List<SubsidiaryInfo> subsidiaryInfos = keyMapper.listFinAllSubsidiaryInfo(nsrsbh);
                newPassbook.addAll(financialServer.setJson(passbooks, subsidiaryInfos.get(0)));
            }
        }
        tPassbookService.updateBatchById(newPassbook);

        for (TPassbook passbook : newPassbook) {
            downLoad(passbook);
        }
        tSourcePassbookMapper.updateIsDownload();
    }

    @Override
    public Boolean downDetailPdf(List<String> invoiceIds) throws UnirestException, IOException {
        for(String invoiceId:invoiceIds)
        {
            TPassbook passbook=tSourcePassbookMapper.selectDetailPdf(invoiceId);
            if(StringUtils.isNotBlank(passbook.getDetailPdf()))
            {
                GetRequest getRequest = sendGet(passbook.getDetailPdf());
                String s = getRequest.asString().getHeaders().toString();
                Pattern r = compile("file[N|n]ame=[^,]+");
                Matcher m = r.matcher(s);
                if (m.find()) {
                    String fileName = m.group(0);
                    fileName = "detail_"+fileName.replaceAll("file[n|N]ame=", "").replace("\"", "").replace("]","");
                    MultipartFile file = new MockMultipartFile(fileName, fileName, ContentType.APPLICATION_OCTET_STREAM.toString(), getRequest.asBinary().getBody());
                    tFileInfoService.uploadFile("system", file, passbook.getIssueDate() + "_" + fileName, passbook.getEInvoiceId(), createPath(passbook));
                    log.info(passbook.getEInvoiceId() + "PDF下载成功");
                } else {
                    log.info(passbook.getEInvoiceId() + "PDF下载失败，该电子票据PDF文件未生成");
                }
            }
        }
        return true;
    }

    @SneakyThrows
    private void downLoad(TPassbook passbook) {
        //下载pdf文件
        if (StringUtils.isNotBlank(passbook.getEinvoicePdf()) && CollectionUtils.isEmpty(tFileInfoMapper.selectByPassbookId(passbook.getEInvoiceId()))) {
            GetRequest getRequest = sendGet(passbook.getEinvoicePdf());
            String s = getRequest.asString().getHeaders().toString();
            Pattern r = compile("file[N|n]ame=[^,]+");
            Matcher m = r.matcher(s);
            if (m.find()) {
                String fileName = m.group(0);
                fileName = fileName.replaceAll("file[n|N]ame=", "").replace("\"", "").replace("]","");
                MultipartFile file = new MockMultipartFile(fileName, fileName, ContentType.APPLICATION_OCTET_STREAM.toString(), getRequest.asBinary().getBody());
                tFileInfoService.uploadFile("system", file, passbook.getIssueDate() + "_" + fileName, passbook.getEInvoiceId(), createPath(passbook));
                log.info(passbook.getEInvoiceId() + "PDF下载成功");
            } else {
                log.info(passbook.getEInvoiceId() + "PDF下载失败，该电子票据PDF文件未生成");
            }
            //下载详情pdf文件
            List<String> invoiceIds=new ArrayList<>();
            invoiceIds.add(passbook.getEInvoiceId());
            downDetailPdf(invoiceIds);

            //合并pfd文件
            for(String incoice:invoiceIds)
            {
                List<TFileInfo> tFileInfos=tFileInfoMapper.selectByPassbookId(incoice);
                if(tFileInfos.size()==0)continue;
                List<File> files=new ArrayList<>();
                List<String> fileId=new ArrayList<>();
                for(int i=0;i<tFileInfos.size();i++)
                {
                    files.add(new File(tFileInfos.get(i).getPath()));
                    fileId.add(tFileInfos.get(i).getId());
                }
                mulFile2One(files,tFileInfos.get(0).getPath());
                String fileName=tFileInfos.get(0).getName();
                for(int i=1;i<tFileInfos.size();i++)
                {
                    FileUtils.deleteQuietly(new File(tFileInfos.get(i).getPath()));
                }
                MultipartFile file = new MockMultipartFile(fileName, fileName, ContentType.APPLICATION_OCTET_STREAM.toString(), new FileInputStream(tFileInfos.get(0).getPath()));
                tFileInfoService.removeByIds(fileId);
                tFileInfoService.uploadFile("system", file, passbook.getIssueDate() + "_" + fileName, passbook.getEInvoiceId(), createPath(passbook));
            }
        }
    }

    private String createPath(TPassbook tPassbook) {
        return filePath + "passbook/" + tPassbook.getIssueDate() + "/";
    }

    private GetRequest sendGet(String url) throws UnirestException {
//        Unirest.setTimeouts(0, 0);
        GetRequest response = Unirest.get(url)
                .header("Authorization", "Basic enBpdXNlcjE6WnBpYXBwbEAxMjM0")
                .header("User-Agent", "apifox/1.0.0 (https://www.apifox.cn)");
        Unirest.clearDefaultHeaders();
        return response;
    }

    private void mulFile2One(List<File> files, String targetPath) throws Exception {
        PDFMergerUtility mergePdf = new PDFMergerUtility();
        for (File f : files) {
            if(f.exists() && f.isFile()){
                // 循环添加要合并的pdf
                mergePdf.addSource(f);
            }
        }
        // 设置合并生成pdf文件名称
        mergePdf.setDestinationFileName(targetPath);
        // 合并pdf
        mergePdf.mergeDocuments(MemoryUsageSetting.setupMainMemoryOnly());
    }
}
